//
// Unihan Input Method
//
// Copyright © 2002-2007 Sun Wah Linux Ltd.
//
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
// USA
//
// $Id: wtpen_wrapper.c 757 2007-05-10 08:19:31Z roger $
//

/*
** $Id: wtpen_wrapper.c 757 2007-05-10 08:19:31Z roger $
*  learn form hwpenx_wrapper which belong to anthonywong :)
*  TKS.
*/

#ifdef HAVE_CONFIG_H
#  include "config.h"
#endif

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
#include <X11/Xlib.h>

#if WTPEN

#include "wtpen_wrapper.h"

#define         WTWINDOW_ATOMNAME            "_WINTONE_WTPEN"
#define         LNX_XIME_WT_SHOW             19
#define         LNX_XIME_WT_HIDE             20

static pid_t pid = -1;
static gboolean setSigHandler = FALSE;

static void wtpen_killed(int);
static sig_t origSigChldHandler = SIG_IGN;
static gboolean RfNotifyWT(Display*, int);

static WTPenXEventHandler wtpen_start_failed_handler = NULL;
static WTPenXEventHandler wtpen_exited_handler = NULL;

static void writeRC(char*);

static char *wtpen_path = NULL;

void
wtpen_set_start_failed_handler(WTPenXEventHandler h)
{
	wtpen_start_failed_handler = h;
}

void
wtpen_set_exited_handler(WTPenXEventHandler h)
{
	wtpen_exited_handler = h;
}

gboolean
is_wtpen_available(void)
{
	if (g_file_test("/usr/bin/wtpen", G_FILE_TEST_IS_EXECUTABLE)) {
		wtpen_path = "/usr/bin/wtpen";
		return 1;
	} else if (g_file_test("/usr/local/bin/wtpen", G_FILE_TEST_IS_EXECUTABLE)) {
		wtpen_path = "/usr/local/bin/wtpen";
		return 1;
	} else if (g_file_test("/usr/share/unihan2/wtpen/wtpen", G_FILE_TEST_IS_EXECUTABLE)) {
		wtpen_path = "/usr/share/unihan2/wtpen/wtpen";
		return 1;
	}
	return 0;
}

gboolean
is_wtpen_started(void)
{
	return (pid != -1 && (kill(pid, 0) == 0));
}

gboolean
wtpen_start(char* region)
{
	char *const argv[2] = { wtpen_path, NULL };

	if (!setSigHandler) {
		origSigChldHandler = signal(SIGCHLD, wtpen_killed);
		setSigHandler = TRUE;
	}
	
	switch (pid = fork()) {
		case -1:	// fork failed?!
			return FALSE;

		case 0:
			writeRC(region);
			execv(wtpen_path, argv);
			_exit(254);	// if we reach here then .. -_-;
	}
	return TRUE;
}

gboolean
wtpen_window_hide(Display* dsp)
{
#if 1
	/* XXX: Dunno how to hide the window atm, so terminate it instead */
	if ( is_wtpen_started() ) {
		return wtpen_quit();
	} else {
	    	return TRUE;
	}
#endif
	//return RfNotifyWT(dsp, LNX_XIME_WT_HIDE);
}

gboolean
wtpen_window_show(Display* dsp)
{
#if 0
	/* XXX: as wtpen_window_hide() is a workaround, so is this one */
	if ( ! is_wtpen_started() ) {
		return wtpen_start();
	} else {
	    	return TRUE;
	}
#endif
	return RfNotifyWT(dsp, LNX_XIME_WT_SHOW);
}

/**
 * Terminate the Hanwang program
 */
gboolean
wtpen_quit(void)
{
	if ( kill(pid, SIGTERM) == 0 ) {
	    pid = 0;
	    return TRUE;
	} else {
	    return FALSE;
	}
}

static gboolean
wtpen_killed_handler(gpointer data)
{
	int retval = GPOINTER_TO_INT(data);

	pid = -1;
	
	if (retval == 254) {
		if (wtpen_start_failed_handler)
			wtpen_start_failed_handler();
	} else {
		if (wtpen_exited_handler)
			wtpen_exited_handler();
	}
	
	return FALSE;
}

static void
wtpen_killed(int signo)
{
	int status, child_val = 0;

	if (waitpid(-1, &status, WNOHANG) > 0) {
		child_val = WEXITSTATUS(status);
	}

	g_idle_add(wtpen_killed_handler, GINT_TO_POINTER(child_val));
}


static gboolean
RfNotifyWT(Display* display, int msg)
{
	Window  win;
	Atom    wtatom;
	XClientMessageEvent event;

	if (msg == LNX_XIME_WT_SHOW)
		printf("msg to wt is SHOW.\n");
	else if(msg == LNX_XIME_WT_HIDE)
		printf("msg to wt is HIDE.\n");

	wtatom = XInternAtom(display, WTWINDOW_ATOMNAME, False);
	win = XGetSelectionOwner(display, wtatom);
	if (win == None)
	{
		printf("WT window is closed.\n");
		return FALSE;
	}
	event.type = ClientMessage;
	event.window = win;
	event.message_type = wtatom;
	event.format = 32;
	sprintf(event.data.b, "wt%d", msg);
	XSendEvent(display, win, False, 0, (XEvent *)&event);

	return TRUE;
}

static void
writeRC(char* region)
{
	char rcfile[FILENAME_MAX];
	char rcdir[FILENAME_MAX];
	int  fd;
	const char wtpenrc_hk[] = 
		"[General]\n"
		"dbcToSbc=false\n"
		"delay=800\n"
		"inkColor=100\n"
		"inkSpeed=15\n"
		"inkStyle=0\n"
		"inkWidth=3\n"
		"inputStyle=0\n"
		"language=0\n"
		"lowToUp=false\n"
		"noInputBuffer=true\n"
		"recRange=206439\n"
		"segment=false\n"
		"sound=false\n"
		"study=false\n"
		"upToLow=false\n";
	const char wtpenrc_cn[] = 
		"[General]\n"
		"dbcToSbc=false\n"
		"delay=800\n"
		"inkColor=100\n"
		"inkSpeed=15\n"
		"inkStyle=0\n"
		"inkWidth=3\n"
		"inputStyle=0\n"
		"language=1\n"
		"lowToUp=false\n"
		"noInputBuffer=true\n"
		"recRange=206439\n"
		"segment=false\n"
		"sound=false\n"
		"study=false\n"
		"upToLow=false\n";
	const char wtpenrc_tw[] = 
		"[General]\n"
		"dbcToSbc=false\n"
		"delay=800\n"
		"inkColor=100\n"
		"inkSpeed=15\n"
		"inkStyle=0\n"
		"inkWidth=3\n"
		"inputStyle=0\n"
		"language=0\n"
		"lowToUp=false\n"
		"noInputBuffer=true\n"
		"recRange=198247\n"
		"segment=false\n"
		"sound=false\n"
		"study=false\n"
		"upToLow=false\n";

	if ( getenv("HOME") == NULL ) {
		return;
	} else {
		strcpy(rcfile, getenv("HOME"));
		strcat(rcfile, "/.wintone/wtpenrc");
		strcpy(rcdir, getenv("HOME"));
		strcat(rcdir, "/.wintone");
	}

	if ( open(rcfile, O_RDONLY) == -1 ) {
		/* no such file exists, create it */
		if ( mkdir(rcdir, 0700) == 0 || errno == EEXIST ) {
			if ( (fd = creat(rcfile, S_IRUSR|S_IWUSR)) == -1 ) {
				return;
			} else {
				if ( strcmp(region,"HK") == 0 ) {
					write(fd, wtpenrc_hk, strlen(wtpenrc_hk));
				} else if ( strcmp(region,"TW") == 0 ) {
					write(fd, wtpenrc_tw, strlen(wtpenrc_tw));
				} else if ( strcmp(region,"CN") == 0 ) {
					write(fd, wtpenrc_cn, strlen(wtpenrc_cn));
				}
				close(fd);
			}
		} else {
			return;
		}
	} else {
		/* file already exists, do nothing */
		return;
	}
}

#endif	/* WTPEN */

// vi:ts=4:nowrap:cin:expandtab
